package org.dromara.app.exception;

import cn.dev33.satoken.exception.NotLoginException;
import cn.dev33.satoken.exception.NotPermissionException;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.domain.R;
import org.dromara.common.core.exception.ServiceException;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpStatus;
import org.springframework.validation.BindException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.multipart.MaxUploadSizeExceededException;

import jakarta.validation.ConstraintViolationException;
import java.io.IOException;

/**
 * App模块专用异常处理器
 * 处理App端特有的业务异常和错误场景
 *
 * @author ruoyi
 */
@Slf4j
@Order(1) // 优先级高于全局异常处理器
@RestControllerAdvice(basePackages = "org.dromara.app")
public class AppExceptionHandler {

    /**
     * App端登录异常处理
     */
    @ExceptionHandler(NotLoginException.class)
    @ResponseStatus(HttpStatus.UNAUTHORIZED)
    public R<Void> handleNotLoginException(NotLoginException e) {
        log.warn("App端用户未登录: {}", e.getMessage());
        return R.fail(401, "请先登录后再操作");
    }

    /**
     * App端权限异常处理
     */
    @ExceptionHandler(NotPermissionException.class)
    @ResponseStatus(HttpStatus.FORBIDDEN)
    public R<Void> handleNotPermissionException(NotPermissionException e) {
        log.warn("App端用户权限不足: {}", e.getMessage());
        return R.fail(403, "权限不足，无法访问该资源");
    }

    /**
     * 文件上传大小超限异常
     */
    @ExceptionHandler(MaxUploadSizeExceededException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public R<Void> handleMaxUploadSizeExceededException(MaxUploadSizeExceededException e) {
        log.error("App端文件上传大小超限: {}", e.getMessage());
        return R.fail("上传文件大小超出限制，请选择较小的文件");
    }

    /**
     * IO异常处理（主要用于文件操作）
     */
    @ExceptionHandler(IOException.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public R<Void> handleIOException(IOException e) {
        log.error("App端文件操作异常: {}", e.getMessage(), e);
        return R.fail("文件操作失败，请稍后重试");
    }

    /**
     * App端业务异常处理
     */
    @ExceptionHandler(ServiceException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public R<Void> handleServiceException(ServiceException e) {
        log.error("App端业务异常: {}", e.getMessage());
        Integer code = e.getCode();
        if (code != null) {
            return R.fail(code, e.getMessage());
        }
        return R.fail(e.getMessage());
    }

    /**
     * 参数验证异常处理
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public R<Void> handleMethodArgumentNotValidException(MethodArgumentNotValidException e) {
        String message = e.getBindingResult().getFieldError().getDefaultMessage();
        log.warn("App端参数验证失败: {}", message);
        return R.fail("参数验证失败: " + message);
    }

    /**
     * 参数绑定异常处理
     */
    @ExceptionHandler(BindException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public R<Void> handleBindException(BindException e) {
        String message = e.getBindingResult().getFieldError().getDefaultMessage();
        log.warn("App端参数绑定失败: {}", message);
        return R.fail("参数绑定失败: " + message);
    }

    /**
     * 约束违反异常处理
     */
    @ExceptionHandler(ConstraintViolationException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public R<Void> handleConstraintViolationException(ConstraintViolationException e) {
        String message = e.getMessage();
        log.warn("App端约束验证失败: {}", message);
        return R.fail("参数验证失败: " + message);
    }



    /**
     * 文件相关异常处理
     */
    @ExceptionHandler(FileException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public R<Void> handleFileException(FileException e) {
        log.error("App端文件异常: {}", e.getMessage());
        return R.fail(e.getCode(), e.getMessage());
    }

    /**
     * 设备相关异常处理
     */
    @ExceptionHandler(DeviceException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public R<Void> handleDeviceException(DeviceException e) {
        log.error("App端设备异常: {}", e.getMessage());
        return R.fail(e.getCode(), e.getMessage());
    }

    /**
     * 版本相关异常处理
     */
    @ExceptionHandler(VersionException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public R<Void> handleVersionException(VersionException e) {
        log.error("App端版本异常: {}", e.getMessage());
        return R.fail(e.getCode(), e.getMessage());
    }

    /**
     * 通用异常处理
     */
    @ExceptionHandler(Exception.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public R<Void> handleException(Exception e) {
        log.error("App端系统异常: ", e);
        return R.fail("系统异常，请联系管理员");
    }

}